Amazon Linux 2 でiSCSIを使ってみる
iSCSIについて
SCSI (Small Computer System Interface) は、ビデオカードやストレージデバイスなどの周辺機器を接続するためのインターフェース規格です。 一方、iSCSI (Internet Small Computer System Interface) は、TCP/IPネットワークを利用して、SCSIコマンドをやりとりするためのプロトコルです。 概ね、SCSIをネットワーク上で使用できるようにしたものがiSCSIです。
SCSIはHDDやSSDなどのブロックデバイスで使用されることがあるのですが、iSCSIでも同様にネットワークを介してブロックデバイスとして認識されます。
近い技術でNFSなどのネットワークファイルシステムがあるのですが、こちらはファイルシステムとして認識されます。 一方、iSCSIではブロックデバイスとして認識されます。
iSCSIの用語解説
- ターゲット
- ストレージを提供する機器のことを指します。ストレージを提供するサーバーがターゲットになります。
- イニシエーター
- ストレージサーバーに対してアクセスするためのクライアントのことを指します。
- バックストア
- iSCSIのターゲットサーバーが扱うストレージ領域のことを指します。バックストアが提供されることで、プログラムがデータを読み書きできるようになります。今回は、EBSをバックストアとして利用します。
- IQN
- iSCSI Qualified Nameの略で、iSCSIで利用されるサーバーまたはストレージの識別子です。識別子ということなので、重複しないように気をつける必要があります。
- 例: iqn.2023-03.com.example:storage0といった形式で表現されます。
- LUN
- Logical Unit Numberの略で、ストレージサーバーから提供される論理的なストレージ領域を指します。ACLを利用し権限を設定することで、複数のクライアントからのアクセスを管理することも可能です。
セットアップ
今回は以下のような構成でサーバーを構築しました。
- ターゲットサーバー(t3.micro) 10GiBのEBSボリュームを別途アタッチ済み
- イニシエーターサーバー(t3.micro)
ターゲットサーバーはTCPの3260番にアクセス可能である必要があるため、セキュリティグループを以下のように設定しておきました。
ちなみに、IQNの仕様はRFCで決まっています。 今回は完全な検証用なので適当に設定しましたが、本番で利用する際は重複やネーミングルールに気を使うと良いでしょう。
- https://tex2e.github.io/rfc-translater/html/rfc3721.html
ターゲット側
ソフトウェアのインストール
まずはじめに、ターゲットサーバーの設定をします。
ターゲットの設定はtargecli
を利用するので、そのインストールを行います。
# ブロックデバイスの確認 $ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT nvme0n1 259:0 0 8G 0 disk ├─nvme0n1p1 259:1 0 8G 0 part / └─nvme0n1p128 259:2 0 1M 0 part nvme1n1 259:3 0 10G 0 disk # <= これをバックストアとして利用する # python-gobjectはtargetcliが依存しているためインストール $ sudo yum install -y targetcli python-gobject.x86_64 $ sudo systemctl start target $ sudo systemctl enable target
ターゲットの設定
インストールが完了したのでtargetcli
を利用してターゲットの設定を行っていきます。
今回はインタラクティブモードでの設定を行います。
$ sudo targetcli Warning: Could not load preferences file /root/.targetcli/prefs.bin. targetcli shell version 2.1.53 Copyright 2011-2013 by Datera, Inc and others. For help on commands, type 'help'. # 現在の状態の確認 /> ls o- / ......................................................................................................................... [...] o- backstores .............................................................................................................. [...] | o- block .................................................................................................. [Storage Objects: 0] | o- fileio ................................................................................................. [Storage Objects: 0] | o- pscsi .................................................................................................. [Storage Objects: 0] | o- ramdisk ................................................................................................ [Storage Objects: 0] o- iscsi ............................................................................................................ [Targets: 0] o- loopback ......................................................................................................... [Targets: 0] # バックストアの作成 /> /backstores/block create name=sample-bs dev=/dev/nvme1n1 Created block storage object sample-bs using /dev/nvme1n1. # iSCSIのターゲットを作成 # ターゲットのIQNをここで指定する。 /> /iscsi create iqn.2023-03.sample.ec2:sample Created target iqn.2023-03.sample.ec2:sample. Created TPG 1. Global pref auto_add_default_portal=true Created default portal listening on all IPs (0.0.0.0), port 3260. # LUNを作成。この際バックストアと関連付ける /> /iscsi/iqn.2023-03.sample.ec2:sample/tpg1/luns create /backstores/block/sample-bs Created LUN 0. # Access Control Listの作成 # iqn.2023-03.sample.ec2:sample-initiatorはクライアント側のIQN /> /iscsi/iqn.2023-03.sample.ec2:sample/tpg1/acls create iqn.2023-03.sample.ec2:sample-initiator Created Node ACL for iqn.2023-03.sample.ec2:sample-initiator Created mapped LUN 0. # ここまでの設定の確認 /> ls o- / ......................................................................................................................... [...] o- backstores .............................................................................................................. [...] | o- block .................................................................................................. [Storage Objects: 1] | | o- sample-bs ................................................................... [/dev/nvme1n1 (10.0GiB) write-thru activated] | | o- alua ................................................................................................... [ALUA Groups: 1] | | o- default_tg_pt_gp ....................................................................... [ALUA state: Active/optimized] | o- fileio ................................................................................................. [Storage Objects: 0] | o- pscsi .................................................................................................. [Storage Objects: 0] | o- ramdisk ................................................................................................ [Storage Objects: 0] o- iscsi ............................................................................................................ [Targets: 1] | o- iqn.2023-03.sample.ec2:sample ..................................................................................... [TPGs: 1] | o- tpg1 ............................................................................................... [no-gen-acls, no-auth] | o- acls .......................................................................................................... [ACLs: 1] | | o- iqn.2023-03.sample.ec2:sample-initiator .............................................................. [Mapped LUNs: 1] | | o- mapped_lun0 ............................................................................. [lun0 block/sample-bs (rw)] | o- luns .......................................................................................................... [LUNs: 1] | | o- lun0 .............................................................. [block/sample-bs (/dev/nvme1n1) (default_tg_pt_gp)] | o- portals .................................................................................................... [Portals: 1] | o- 0.0.0.0:3260 ..................................................................................................... [OK] o- loopback ......................................................................................................... [Targets: 0] # ユーザーの認証情報の設定 # 認証方法はCHAPが利用される /> /iscsi/iqn.2023-03.sample.ec2:sample/tpg1/acls/iqn.2023-03.sample.ec2:sample-initiator set auth userid=sample-user Parameter userid is now 'sample-user'. /> /iscsi/iqn.2023-03.sample.ec2:sample/tpg1/acls/iqn.2023-03.sample.ec2:sample-initiator set auth password=supersecret Parameter password is now 'supersecret'. # 設定を保存し終了 /> saveconfig Configuration saved to /etc/target/saveconfig.json /> exit Global pref auto_save_on_exit=true Last 10 configs saved in /etc/target/backup/. Configuration saved to /etc/target/saveconfig.json
イニシエーター
次にイニシエータの設定をします。
# イニシエーターのソフトウェアのインストール $ sudo yum install iscsi-initiator-utils -y # ターゲットの探索 # 成功すると利用可能なターゲットが情報が取得できる $ sudo iscsiadm -m discovery -t st -p <ターゲットサーバーのIP> <ターゲットサーバーのIP>,1 iqn.2023-03.sample.ec2:sample # イニシエーターのIQNを設定 $ sudo nano /etc/iscsi/initiatorname.iscsi # 以下に変更する InitiatorName=iqn.2023-03.sample.ec2:sample-initiator # イニシエーター側に認証情報を設定する $ sudo nano /etc/iscsi/iscsid.conf # 以下のように設定します。(設定ファイルより一部抜粋) # ************* # CHAP Settings # ************* # To enable CHAP authentication set node.session.auth.authmethod # to CHAP. The default is None. node.session.auth.authmethod = CHAP # To set a CHAP username and password for initiator # authentication by the target(s), uncomment the following lines: node.session.auth.username = sample-user node.session.auth.password = supersecret # iscsidサービスを再起動し、設定を読み込ませる sudo systemctl restart iscsid.service # ログインする $ sudo iscsiadm -m node -T iqn.2023-03.sample.ec2:sample --login Logging in to [iface: default, target: iqn.2023-03.sample.ec2:sample, portal: <ターゲットサーバーのIP>,3260] (multiple) Login to [iface: default, target: iqn.2023-03.sample.ec2:sample, portal: <ターゲットサーバーのIP>,3260] successful. # ブロックデバイスの確認 $ lsblk -fs NAME FSTYPE LABEL UUID MOUNTPOINT sda ext4 1f4b506d-8390-4e6a-92bc-e52f1d45f602 # <= これがiSCSIで利用できるデバイス nvme0n1p1 xfs / 80b3e64c-379e-4297-a6a1-356635495cfc / └─nvme0n1 nvme0n1p128 └─nvme0n1
無事に、ブロックデバイスとしてsdaが認識されました。
せっかくなので、ext4でファイルシステムを構築し、マウントしてみます。 ここからの流れはEBSでマウントするのと同じです。
# EXT4でファイルシステムを作成 $ sudo mkfs.ext4 /dev/sda mke2fs 1.42.9 (28-Dec-2013) /dev/sda is entire device, not just one partition! Proceed anyway? (y,n) y # 今回はパーティションを分けていないため警告が出ているが「y」で実行する Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) Stride=0 blocks, Stripe width=0 blocks 655360 inodes, 2621440 blocks 131072 blocks (5.00%) reserved for the super user First data block=0 Maximum filesystem blocks=2151677952 80 block groups 32768 blocks per group, 32768 fragments per group 8192 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632 Allocating group tables: done Writing inode tables: done Creating journal (32768 blocks): done Writing superblocks and filesystem accounting information: done # マウント先のディレクトリの作成 $ sudo mkdir -p /mnt/iscsi # fstabを編集し、自動でマウントするように設定 $ sudo nano /etc/fstab # 以下のように設定(1行目はルートファイルシステムなので変更しない UUID=80b3e64c-379e-4297-a6a1-356635495cfc / xfs defaults,noatime 1 1 UUID=1f4b506d-8390-4e6a-92bc-e52f1d45f602 /mnt/iscsi ext4 defaults,noatime 0 2 # マウント $ sudo mount -a $ lsblk -fs NAME FSTYPE LABEL UUID MOUNTPOINT sda ext4 1f4b506d-8390-4e6a-92bc-e52f1d45f602 /mnt/iscsi nvme0n1p1 xfs / 80b3e64c-379e-4297-a6a1-356635495cfc / └─nvme0n1 nvme0n1p128 └─nvme0n1
無事にext4としてマウントされました。
終わりに
今回はiSCSIをAL2上で利用する方法について整理しました。
EBSでも複数のインスタンスにアタッチできたりするのであまり出番は無いかもしれません... ただ、既存システムからの移行などでどうしてもiSCSIを利用したい局面などでは便利なんじゃないでしょうか?
付録
今回はハイパーバイザがNitroであるt3インスタンスを利用しましたが、Xen系であるt2などでは少し挙動が変わったりします。
実は、AL2内のudevルールでは/dev/xvda
に対して/dev/sda
にシンボリックリンクが作成されます。
この関係で、イニシエーター側でXenのインスタンスを利用するとシンボリックリンクとiscsid
のデバイスが衝突して上手く/dev/sda
が使えなくなります。
つまるところ、ファイルシステムの作成やマウントなどで不都合が生じます。
以下がそのルールです。
NitroのインスタンスではEBSはnvme*
として認識されるので、udevのルールに引っかからず、シンボリックリンクが自動で作成されません。